package com.example.javaproject.thread.productandconsumer;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Description: 利用ReentrantLock实现生产者消费者
 * <br>Author：tian
 * <br>Time: 2019/3/5 15:50
 */
public class ReentrantLockImpProducerConsumer {
    private static final Lock lock = new ReentrantLock();

    private static final Condition full = lock.newCondition();
    private static final Condition empty = lock.newCondition();

    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        ExecutorService service = Executors.newFixedThreadPool(15);

        for (int i = 0; i < 5; i++) {
            service.submit(new Producer(list, 8, lock));
        }

        for (int i = 0; i < 10; i++) {
            service.submit(new Consumer(list, lock));
        }
    }

    static class Producer implements Runnable {

        private final List<Integer> list;
        private final int maxLength;
        private final Lock lock;

        public Producer(List<Integer> list, int maxLength, Lock lock) {
            this.list = list;
            this.maxLength = maxLength;
            this.lock = lock;
        }

        @Override
        public void run() {
            while (true) {
                lock.lock();
                try {
                    while (maxLength == list.size()) {
                        System.out.println("生产者:" + Thread.currentThread().getName() + " list达到最大容量，进行wait");
                        full.await();
                        System.out.println("生产者:" + Thread.currentThread().getName() + " 退wait");
                    }

                    Random random = new Random();
                    int item = random.nextInt();
                    System.out.println("生产者:" + Thread.currentThread().getName() + " 生成数据 " + item);
                    list.add(item);
                    empty.signalAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }
    }

    static class Consumer implements Runnable {
        private List<Integer> list;
        private Lock lock;

        public Consumer(List<Integer> list, Lock lock) {
            this.list = list;
            this.lock = lock;
        }

        @Override
        public void run() {
            while (true) {
                lock.lock();
                try {
                    while (list.size() == 0) {
                        System.out.println("消费者" + Thread.currentThread().getName() + "  list为空，进行wait");
                        empty.await();
                        System.out.println("消费者" + Thread.currentThread().getName() + "  退出wait");
                    }
                    Integer element = list.remove(0);
                    System.out.println("消费者" + Thread.currentThread().getName() + "  消费数据：" + element);
                    full.signalAll();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }
    }
}
